package generate

import (
	"fmt"
	"io"
	"modeltools/conf"
	"modeltools/dbtools"
	"os"
	"strings"
)

func Genertate(tableNames ...string) {
	tableNamesStr := ""
	for _, name := range tableNames {
		if tableNamesStr != "" {
			tableNamesStr += ","
		}
		tableNamesStr += "'" + name + "'"
	}
	tables := getTables(tableNamesStr) //生成所有表信息
	//tables := getTables("admin_info","video_info") //生成指定表信息，可变参数可传入过个表名
	for _, table := range tables {
		fields := getFields(table.Name)
		generateModel(table, fields)
	}
}

// 获取表信息
func getTables(tableNames string) []Table {
	db := dbtools.GetMysqlDb()
	var tables []Table
	if tableNames == "" {
		db.Raw("SELECT TABLE_NAME as Name,TABLE_COMMENT as Comment FROM information_schema.TABLES WHERE table_schema='" + conf.MasterDbConfig.DbName + "';").Find(&tables)
	} else {
		db.Debug().Raw("SELECT TABLE_NAME as Name,TABLE_COMMENT as Comment FROM information_schema.TABLES WHERE TABLE_NAME IN (" + tableNames + ") AND table_schema='" + conf.MasterDbConfig.DbName + "';").Find(&tables)
	}
	return tables
}

// 获取所有字段信息
func getFields(tableName string) []Field {
	db := dbtools.GetMysqlDb()
	var fields []Field
	db.Raw("show FULL COLUMNS from " + tableName + ";").Find(&fields)
	return fields
}

// 判断文件夹是否存在
func PathExists(path string) (bool, error) {
	_, err := os.Stat(path)
	if err == nil {
		return true, nil
	}
	if os.IsNotExist(err) {
		return false, nil
	}
	return false, err
}
func generateDir(s string) {
	//_dir := "" + s + ""
	_dir := s
	exist, err := PathExists(_dir)
	if err != nil {
		fmt.Printf("get dir error![%v]\n", err)
		return
	}
	if exist {
		fmt.Printf("has dir![%v]\n", _dir)
	} else {
		fmt.Printf("no dir![%v]\n", _dir)
		// 创建文件夹
		err := os.MkdirAll(_dir, os.ModePerm)
		if err != nil {
			fmt.Printf("mkdir failed![%v]\n", err)
		} else {
			fmt.Printf("mkdir success!\n")
		}
	}
}

// 生成Model
func generateModel(table Table, fields []Field) {
	setFun := ""
	content := "package Field\n\n"
	//content += `import "time"` + "\n\n"
	content += setFun

	content += "type " + CamelCase(table.Name) + "Req" + " struct {\n"
	//这里开始
	for _, field := range fields {
		fieldName := CamelCase(field.Field)
		fieldType := getFiledType(field)
		fieldJson := getFieldJson(field)
		fieldComment := getFieldComment(field)
		content += "	" + fieldName + " " + fieldType + " `" + fieldJson + fieldComment + "\n"
	}

	content += "}\n\n"

	/*===========================================生成返回数据结构体====================================*/
	if len(table.Comment) > 0 {
		content += "// " + CamelCase(table.Name) + " " + table.Comment + "\n"
	}
	content += "type " + CamelCase(table.Name) + " struct {\n"

	for _, field := range fields {
		fieldName := CamelCase(field.Field)

		fieldGorm := getFieldGorm(field)
		field.Field = CamelCase(field.Field)
		fieldType := getFiledType(field)
		fieldComment := getFieldComment(field)
		content += "	" + fieldName + " " + fieldType + " `" + fieldGorm + "` " + fieldComment + "\n"

		//生成方法
		//setFun += getFunGet(generator.CamelCase(table.Name), field)

	}

	content += "}\n"

	setFun += "\n\n"

	setFun += getTableName(CamelCase(table.Name), table.Name)
	content += setFun
	//fmt.Println(content1)
	//fileModelPath := conf.ModelPath + "Module" + generator.CamelCase(table.Name) + "/Model/"
	//fileModulePath := conf.ModelPath + "Module" + generator.CamelCase(table.Name) + "/Module/"
	//fileSerializableDataPath := conf.ModelPath + "Module" + generator.CamelCase(table.Name) + "/SerializableData/"
	fileSerializableDataPath := conf.ModelPath
	//fileApiPath := conf.ModelPath + "Module" + generator.CamelCase(table.Name) + "/Api/"
	//fileInterfaceDataPath := conf.ModelPath + "Module" + generator.CamelCase(table.Name) + "/Interface/"
	//generateDir(fileModelPath)
	//generateDir(fileModulePath)
	//generateDir(fileSerializableDataPath)
	//generateDir(fileApiPath)
	//generateDir(fileInterfaceDataPath)

	filename := fileSerializableDataPath + CamelCase(table.Name) + ".go"
	var f *os.File
	var err error

	generateDir(conf.ModelPath)

	if checkFileIsExist(filename) {
		if !conf.ModelReplace {
			fmt.Println(CamelCase(table.Name) + " 已存在，需删除才能重新生成...")
			return
		}

		f, err = os.OpenFile(filename, os.O_WRONLY|os.O_TRUNC, 0666) //打开文件
		if err != nil {
			panic(err)
		}
	} else {
		f, err = os.Create(filename)
		if err != nil {
			panic(err)
		}
	}
	defer f.Close()
	_, err = io.WriteString(f, content)
	if err != nil {
		panic(err)
	} else {
		fmt.Println(CamelCase(table.Name) + " 已生成...")
	}
}

// 获取字段类型
func getFiledType(field Field) string {
	typeArr := strings.Split(field.Type, "(")

	switch typeArr[0] {
	case "int":
		return "int"
	case "integer":
		return "int"
	case "mediumint":
		return "int"
	case "bit":
		return "int"
	case "year":
		return "int"
	case "smallint":
		return "int"
	case "tinyint":
		return "int"
	case "bigint":
		return "int64"
	case "decimal":
		return "float32"
	case "double":
		return "float32"
	case "float":
		return "float32"
	case "real":
		return "float32"
	case "numeric":
		return "float32"
	case "timestamp":
		return "time.Time"
	case "datetime":
		return "time.Time"
	case "time":
		return "time.Time"
	default:
		return "string"
	}
}

// 获取字段json描述
func getFieldJson(field Field) string {
	return `json:"` + field.Field + `"` + " " + `form:` + `"` + field.Field + `"` + "`"
}

func getFieldGorm(field Field) string {
	//不带json tag的
	//return `gorm:"column:` + field.Field + `"`
	return `json:"` + field.Field + `"` + ` ` + `gorm:"column:` + field.Field + `"`

}

// 获取字段说明
func getFieldComment(field Field) string {
	if len(field.Comment) > 0 {

		return "// " + field.Comment
	}
	return ""
}

func getTableName(struceName string, tableName string) string {
	return "func (this " + "*" + struceName + ") TableName() string {" + "\n\t" + "return \"" + tableName + `"` + "\n}"
}

func getFunGet(tableName string, field Field) string {
	//fix := strings.ToLower(tableName[:1])
	//return "func ("+fix+" "+tableName+")Get"+field.Field+"()"+getFiledType(field)+"{return "+fix+"."+field.Field+"}\n"
	return "func (this *" + tableName + ")Get" + field.Field + "()" + getFiledType(field) + "{return this." + field.Field + "}\n"
}

// 检查文件是否存在
func checkFileIsExist(filename string) bool {
	var exist = true
	if _, err := os.Stat(filename); os.IsNotExist(err) {
		exist = false
	}
	return exist
}
